<?php
class SurveysController extends AppController {
	var $name = 'Surveys';
	
	var $paginate = array(
		'limit' => 50,
		'conditions' => array('Survey.isDeleted' => 0),
		'order' => array('Survey.created' => 'DESC'),
		'group' => array('Survey.id')
	);
	
	var $uses = array('User', 'Survey', 'Audiencelist', 'Question');
	
	/**
	 * Display surveys created by the logged in user
	 * 
	 * @return 
	 */
	function index() {
		$this->set('external_css', array('surveys.css'));
		
		$this->_getSurveys();
	}
	
	/**
	 * Add a new survey
	 * 
	 * @return 
	 */
	function add() {
		if (!empty($this->data)) {
			
			$active_user = $this->Auth->user();
			
			$this->data['Survey']['created_by'] = $active_user['User']['id'];  //Save who created this survey
			$this->data['SurveyType']['type'] = 'Incomplete';  //Set the intial survey type to incomplete
			
			// Set the survey data.
			$this->Survey->set($this->data);
			
			//Check if the survey is valid
			if ($this->Survey->validates()) {
				//Save the survey
				$this->Survey->saveAll($this->data);
				//Get the new survey id
				$surveyId = $this->Survey->id;
				
				$this->_addQuestionAndAnswer($surveyId);
				
				// Create a default, empty Audience list for this survey
				$this->loadModel('Audiencelist');
				$audiencelist['Audiencelist'] = $this->data['Survey'];
				$this->Audiencelist->create($audiencelist);
				$audiencelist['Audiencelist']['user_id'] = $active_user['User']['id'];
				$this->Audiencelist->save($audiencelist);
				$this->Survey->habtmAdd('Audiencelist', $this->Survey->id, $this->Audiencelist->id);
				
				//$this->Session->setFlash('A new survey has been added.');
				$this->redirect(array('controller' => 'surveys', 'action' => 'edit', 'id' => $surveyId));
			}
		}
	}
	
	/**
	 * Edit a survey
	 * 
	 * @param object $id [optional]
	 * @return 
	 */
	function edit($id = null) {
		
		// Make sure the user actually owns the given survey
		if(! $this->_doesSurveyBelongToAuthedUser($id)){
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
			return;
		}
		
		// Grab the active user (useful in a variety of places)
		$active_user = $this->Auth->user();
		
		//Set the id to edit
		$this->Survey->id = $id;
		
		//Set whether or not this survey is open
		$survey = $this->Survey->read();
		$type = $survey['SurveyType']['type'];
		$open = false;
		if($type == "Available" || $type == "Restricted" || $type == "Private") {
			$open = true;
		}
		$this->set('open', $open);
		
		// Set the survey id in the view
		$this->set('survey_id', $id);
		$this->set('survey_type', $type);
		
		$questions = array();
		$answers = array();
		$questionDropDown = array();
		
		// Find all the Questions this survey has
		$this->Question->Behaviors->attach('Containable');
		$this->Question->bindModel(array('hasOne' => array('QuestionsSurvey')));
		$questions = $this->Question->find('all', array(
			'conditions' => array('QuestionsSurvey.survey_id' => $id, 'Question.isDeleted' => 0),
			'order' => array('Question.viewOrder ASC'),
			'contain' => array('QuestionsSurvey')
		));
		
		$this->loadModel('Answer');
		$q = 0;
		//Loop through the questions and get the answers for each
		foreach($questions as $question) {
			//Populate the drop down list
			$questionDropDown[$question['Question']['id']] = 'Question '.($q+1);
			
			$this->Answer->Behaviors->attach('Containable');
			$tempAnswers = $this->Answer->find('all', array(
				'conditions' => array(
					'Answer.question_id' => $question['Question']['id'],
					'Answer.isDeleted' => 0
				),
				'order' => array('Answer.viewOrder ASC')
			));
			
			for($a = 0; $a < count($tempAnswers); $a++) {
				$answers[$q][$a] = $tempAnswers[$a]['Answer'];
			}			
			$q++;
		}
		
		$this->set('answers', $answers);
		$this->set('questions', $questions);
		$this->set('questionDropDown', $questionDropDown);
		
		if (empty($this->data)) {
			//if the post data is empty, populate the current data
			$this->data = $survey;
		} else {
			//otherwise save the survey
			$this->_saveSurvey($this->data, $id);
			$this->redirect(array('controller' => 'surveys', 'action' => 'edit', 'id' => $id));
		}
	}
	
	function add_question() {
		if(!empty($this->data)) {
			//Get the survey ID and save a new question
			$surveyId = $this->data['Survey']['IdQ'];
			
			// Make sure the user actually owns the given survey
			if(! $this->_doesSurveyBelongToAuthedUser($surveyId)){
				$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
				return;
			}
			
			$this->_addQuestionAndAnswer($surveyId);
			$this->redirect(array('controller' => 'surveys', 'action' => 'edit', 'id' => $surveyId));
		} else {
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
		}
	}
	
	function add_answer() {
		if(!empty($this->data)) {
			$surveyId = $this->data['Survey']['IdA'];
			
			// Make sure the user actually owns the given survey
			if(! $this->_doesSurveyBelongToAuthedUser($surveyId)){
				$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
				return;
			}
			
			$questionId = $this->data['Question']['id'];
			$this->loadModel('Answer');
				
			//Get the current max answer vieworder
			$ansOrder = $this->Answer->find('first', array(
				'fields' => array('Answer.viewOrder'),
				'order' => array('Answer.viewOrder DESC')
				)
			);
			$newAO = $ansOrder['Answer']['viewOrder'];
			$newAO++;
			
			//Create a blank answer and add it to the question
			$this->Answer->id = null;
			$answer = array();
			$answer['Answer']['question_id'] = $questionId;
			$answer['Answer']['viewOrder'] = $newAO;
			$answer['Answer']['text'] = "Answer Text";
			$this->Answer->save($answer);
			
			$this->redirect(array('controller' => 'surveys', 'action' => 'edit', 'id' => $surveyId));
		} else {
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
		}
	}
	
	/**
	 * Get all surveys of type closed created by this user
	 * 
	 * @return 
	 */
	function closed_surveys() {
		$this->Session->write($this->name.'.searchPreResName', "");
		$this->Session->write($this->name.'.searchPreResUUID', "");
		$this->Session->write($this->name.'.searchPreResType', "Closed");
		
		$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
	}
	
	/**
	 * Get all surveys created by this user
	 * 
	 * @return 
	 */
	function show_all() {
		$this->Session->write($this->name.'.searchPreResName', "");
		$this->Session->write($this->name.'.searchPreResUUID', "");
		$this->Session->write($this->name.'.searchPreResType', "");
		
		$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
	}
	
	/**
	 * Gets the audience list data for the given survey
	 * 
	 * @param object $id [optional]
	 * @return 
	 */
	function audience_list($id = null) {
		// Grab the active user (useful in a variety of places)
		$active_user = $this->Auth->user();
		
		//Set the id to edit
		$this->Survey->id = $id;
		
		// Make sure the user actually owns the given survey
		if(! $this->_doesSurveyBelongToAuthedUser($id)){
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
			return;
		}
		
		// assume we are not displaying search results
		$this->set('display', false);

		$this->set('survey_id', $id);
		
		if (empty($this->data)) {
			//if the post data is empty, populate the current data
			$this->data = $this->Survey->read();
		
		} else {
		
			if($this->Session->check($this->name.'.searchName'))
			{
	        	$searchName = $this->Session->read($this->name.'.searchName');
			}
	
			$searchName = trim($this->data['User']['username']);
	    	$filters = array();
			$this->set('searchName', '');
		
	    	if(isset($searchName)) {
	    		//Set up the search filters
	        	$filters = array('lower(User.username) LIKE' => '%'.low($searchName).'%');
	        	$this->Session->write($this->name.'.searchName', $searchName);
				$this->set('searchName', $searchName);
				$this->paginate = array('order'=>array('User.username'=>'asc'));
				$this->set('users', $this->paginate('User', $filters));
				
				// display search results
				$this->set('display', true);
	    	}
		}
		//Flag whether or not to display results
		$this->set('searchName', 'Enter a user name for which to search');
		
		// find all the audience lists associated with the active user
		$this->User->bindModel(array('hasMany' => array('Audiencelists')));
		
		$users_audiencelists = $this->Audiencelist->find('all', 
				array('fields' => array('id', 'name'), 
				'conditions' => array('Audiencelist.user_id'=>$active_user['User']['id'])));
						
		$this->set('usersAudienceLists', $users_audiencelists);
		
		// bind the survey to get the survey's only audience list
		$this->Survey->bindModel(array('hasOne' => array('AudiencelistsSurveys')));
		$surveys_audiencelist =	$this->Survey->find('all', array(
				'fields' => array('Survey.*'),
				'conditions'=>array('AudiencelistsSurveys.survey_id'=>$id, ), // id of survey
		));
		
		// TODO: the assumption that a survey only has one audience list is not enforced
		// this could impair long-term modifiability
		$surveys_audiencelist = $surveys_audiencelist[0]['Audiencelist'];
		
		$this->User->bindModel(array('hasOne'=>array('AudiencelistsUsers')));
		$preregistered_users = $this->User->find('all', array(
			'fields' => array('User.username', 'User.firstname', 'User.lastname'),
			'conditions'=>array('AudiencelistsUsers.audiencelist_id'=>$surveys_audiencelist[0]['id'])
		));
		
		$this->set('preregistered_users', $preregistered_users);
		$this->set('surveys_audiencelist_id', $surveys_audiencelist[0]['id']);
		$this->set('audiencelist_name', $surveys_audiencelist[0]['name']);
	}
	
	/**
	 * Change the type of a survey
	 * 
	 * @param object $id [optional]
	 * @return 
	 */
	function change_type($id = null) {
		$this->Survey->id = $id;
		$this->Survey->SurveyType->deleteAll(array('survey_id' => $id));  //Delete the existing survey type

		$this->Survey->saveAll($this->data);
		
		$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
	}
	
	/**
	 * Provide an overview of the given survey for a presenter 
	 * 
	 * @param object $id 
	 * @return 
	 */
	function view($id) {
		// Make sure the user actually owns the given survey
		if(! $this->_doesSurveyBelongToAuthedUser($id)){
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
			return;
		}
		
		$this->Survey->id = $id;
		$thisSurvey = $this->Survey->find();
		$this->set('thisSurvey', $thisSurvey);
		
		// Find all the Questions this survey has
		$this->Question->bindModel(array('hasOne' => array('QuestionsSurveys')));
		$questions = $this->Question->find('all', array(
						'fields' =>array('Question.*'),
						'conditions' =>array('QuestionsSurveys.survey_id' => $id)
		));
		
		// Array of Question / Response pairs: { {Q1R1, Q1R2} {Q2R1, Q2R2, Q2R3}...}
		$this->loadModel('Answer');
		$this->Answer->Behaviors->attach('Containable');
		$responses = array();
		foreach($questions as $question){
			$responses[] = $this->Answer->find('all', array(
				'conditions' => array(
					'Answer.question_id' => $question['Question']['id'],
					'Answer.isDeleted' => 0
				),
				'order' => array('Answer.viewOrder ASC')
			));
		}
		
		$this->set('responses', $responses);
		
		// Find all the users registered for this survey
		$this->Survey->bindModel(array('hasOne' => array('SurveysUser')));
		$registeredUsers =	$this->Survey->find('all', array(
				'fields' => array('Survey.*'),
				'conditions'=>array('SurveysUser.survey_id'=>$id, ), // id of survey
		));
		if(count($registeredUsers) > 0){
		$registeredUsers = $registeredUsers[0]['User'];
			$this->set('registeredUsers', $registeredUsers);
		}
		else{
			$this->set('registeredUsers', array());
		}
	}
	
	/**
	 * Provide the users view of the survey
	 * 
	 * @param object $survey_id
	 * @param object $question_number
	 * @return 
	 */
	function user_view($survey_id, $question_number) {
		$user_data = $this->Auth->user();
		$this->Survey->id = $survey_id;
		$thisSurvey = $this->Survey->find();
		
		$this->set('thisSurvey', $thisSurvey);
		
		$this->loadModel('Question');
		// Grab only the questions associated with this survey and store them in the 'questions' variable
		$this->Question->bindModel(array('hasOne' => array('QuestionsSurvey')));
		$questions = $this->Question->find('all', array(
				'fields' => array('Question.*'),
				'conditions'=>array('QuestionsSurvey.survey_id'=>$survey_id, // id of survey
									'Question.isDeleted' => '0'), // make sure the question isn't deleted
				'order'=>array('Question.viewOrder ASC')
		));
		
		$this->loadModel('Answer');
		$this->Answer->Behaviors->attach('Containable');
		$answers = $this->Answer->find('all', array(
			'conditions' => array(
				'Answer.question_id' => $questions[$question_number-1]['Question']['id'],
				'Answer.isDeleted' => 0
			),
			'order' => array('Answer.viewOrder ASC')
		));
		
		$this->loadModel('User');
		$this->User->bindModel(array('hasOne' => array('SurveysUser')));
		$thisUser = $this->Auth->user();
		$registered = $this->User->find('count', array(
			'conditions' => array(
				'SurveysUser.survey_id' => $survey_id,
				'SurveysUser.user_id' => $thisUser['User']['id']
			)
		));
		
		// load a splash page if there are no questions
		if(count($questions) == 0){
			$this->set('survey_id', $survey_id);
			$this->set('question_number', 'No questions are available yet');
			$this->set('questions', array());
			$this->set('user_id', $user_data['User']['id']);
			$this->set('questions_surveys_id',null);
			$this->set('registered', $registered);
		}
		else{
			$this->set('survey_id', $survey_id);
			$this->set('question_number', $question_number);
			$this->set('questions', $questions);
			$this->set('answers', $answers);
			$this->set('user_id', $user_data['User']['id']);
			$this->set('questions_surveys_id', $questions[$question_number-1]['Survey'][0]['QuestionsSurvey']['id']);
			$this->set('registered', $registered);
		}
	}
	
	/**
	 * Save a users response to a question
	 * 
	 * @return 
	 */
	function submit_answer() {
		$this->loadModel('Response');
		
		// Store the response data from the form.
		$response['Response'] = $this->data['Survey'];
		
		// Find out of the user has already answered this survey's question in the past.
		$thisResp = $this->Response->find('first', array(
			'conditions' => array(
				'Response.user_id' => $response['Response']['user_id'],
				'Response.questions_surveys_id' => $response['Response']['questions_surveys_id']
			)
		));

		// If the user has answered in the past, simply change the answer rather than creating a new response.
		if($thisResp) {
			$this->Response->read(NULL, $thisResp['Response']['id']);
		}
		
		// Validate and save the response.
		if($this->Response->validates())
		{
			$this->Response->save($response);
			
			if(empty($response['Response']['end'])) {
				$this->redirect(array('action' => 'user_view', $this->data['Survey']['survey_id'], $this->data['Survey']['question_number']+1));
			} else {
				$this->Session->setFlash('Thank you for completing the survey.');
				$this->redirect(array('controller' => 'audiences', 'action' => 'index'));
			}
		}
		else
		{
			$this->redirect(array('action' => 'user_view', $this->data['Survey']['survey_id'], $this->data['Survey']['question_number']));
		}
	}
	
	/**
	 * Delete a survey
	 * 
	 * @param object $id
	 * @return 
	 */
	function delete($id) {
		// Make sure the user actually owns the given survey
		if(! $this->_doesSurveyBelongToAuthedUser($id)){
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
			return;
		}
		
		
		$this->Survey->id = $id;
		$this->data['Survey']['isDeleted'] = 1;
		if($this->Survey->save($this->data)){
			$this->Session->setFlash("Survey deleted");
			$this->redirect(array('action' =>'index'));
		}
	}
	
	/**
	 * Add the user to an audience list
	 * 
	 * @param object $survey_id
	 * @param object $user_id
	 * @return 
	 */
	function addUserToAudienceList($survey_id, $user_id){
		// Make sure the user actually owns the given survey
		if(! $this->_doesSurveyBelongToAuthedUser($id)){
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
			return;
		}
		
		$this->_addUserToAudienceList($survey_id, $user_id);
			
		// go back to the edit survey page
		$this->redirect(array('controller' => 'surveys', 'action' => 'edit', $survey_id));
	}
	
	/**
	 * Save the survey data given in $data for the given survey id
	 * 
	 * @param object $data
	 * @param object $surveyId
	 * @return 
	 */
	function _saveSurvey($data, $surveyId) {
		//Set the id to edit
		$this->Survey->id = $surveyId;
		
		// Make sure the user actually owns the given survey
		if(! $this->_doesSurveyBelongToAuthedUser($surveyId)){
			$this->redirect(array('controller' => 'surveys', 'action' => 'index'));
			return;
		}
		
		$surveyName = trim($data['Survey']['name']);
		if(empty($surveyName)) {
			$surveyName = 'Survey Name';
		}
		
		$this->Survey->set('name', $surveyName);
		$this->Survey->save();
		
		$this->loadModel('Answer');
		$q = 0;			
		
		//Loop through questions
		foreach($data['Question'] as $question) {
			$this->Question->id = $question['id'];
			
			$question['text'] = trim($question['text']);
			
			if(empty($question['text'])) {
				$question['text'] = 'Question Text';
			}
			
			$questionData['Survey']['id'] = $surveyId;
			$questionData['Question'] = $question;
			
			//Save the question
			$this->Question->save($questionData);
			
			//Loop through the answers for this question
			foreach($data['Answer'][$q] as $answer) {
				$this->Answer->id = $answer['id'];
				
				$answer['text'] = trim($answer['text']);
				
				if(empty($answer['text'])) {
					$answer['text'] = 'Answer Text';
				}
				
				$this->Answer->set('text', $answer['text']);
				
				//Save answer
				$this->Answer->save($answer);
			}
			$q++;
		}
	}
	
	/**
	 * Add one question and two answers to the given survey
	 * 
	 * @param object $surveyId
	 * @return 
	 */
	function _addQuestionAndAnswer($surveyId) {
		$this->loadModel('Question');
		$this->loadModel('Answer');
		
		//Get the current max question vieworder
		$quesOrder = $this->Question->find('first', array(
			'fields' => array('Question.viewOrder'),
			'order' => array('Question.viewOrder DESC')
			)
		);
		$newQO = $quesOrder['Question']['viewOrder'];
		$newQO++;
		
		//Create one blank question and add it to this survey
		$this->Question->id = null;
		$question = array();
		$question['Survey']['id'] = $surveyId;
		$question['Question']['text'] = "Question Text";
		$question['Question']['viewOrder'] = $newQO;
		$this->Question->save($question);
		$questionId = $this->Question->id;
		
		//Get the current max answer vieworder
		$ansOrder = $this->Answer->find('first', array(
			'fields' => array('Answer.viewOrder'),
			'order' => array('Answer.viewOrder DESC')
			)
		);
		$newAO = $ansOrder['Answer']['viewOrder'];
		$newAO++;
		
		//Create two blank answers and add them to the question
		$this->Answer->id = null;
		$answer = array();
		$answer['Answer']['question_id'] = $questionId;
		$answer['Answer']['viewOrder'] = $newAO;
		$answer['Answer']['text'] = "Answer Text";
		$this->Answer->save($answer);
		
		$this->Answer->id = null;
		$newAO++;
		$answer['Answer']['viewOrder'] = $newAO;
		$this->Answer->save($answer);
	}
	
	/**
	 * Checks to see if the specified survey belongs to the logged in user
	 * 
	 * @param object $survey_id
	 * @return 
	 */
	function _doesSurveyBelongToAuthedUser($survey_id){
		$active_user = $this->Auth->user();
		$surveys = $this->Survey->find('all', array(
			'conditions' => array('Survey.id' => $survey_id, 'Survey.created_by' => $active_user['User']['id']),
		));
		
		if(empty($surveys)){
			$this->Session->setFlash('Could not perform the specified operation. Please try again');
			return false;
		}
		else return true;
	}
	
	/**
	 * Adds a user to the audience list
	 * 
	 * @param object $survey_id
	 * @param object $user_id
	 * @return 
	 */
	function _addUserToAudienceList($survey_id, $user_id){
		// Load the survey
		$this->Survey->id = $survey_id;
		$this->data = $this->Survey->read();
		
		// bind the survey to get the survey's only audience list
		$this->Survey->bindModel(array('hasOne' => array('AudiencelistsSurveys')));
		$surveys_audiencelist =	$this->Survey->find('all', array(
				'fields' => array('Survey.*'),
				'conditions'=>array('AudiencelistsSurveys.survey_id'=>$survey_id, ), // id of survey
		));
		
		// TODO: the assumption that a survey only has one audience list is not enforced
		// this could be a bad thing
		$surveys_audiencelist = $surveys_audiencelist[0]['Audiencelist'];
			
		// load the audience list
		$this->Audiencelist->id = $surveys_audiencelist[0]['id'];
		$this->Audiencelist->read();
			
		// add the entry for the given user
		$this->User->habtmAdd('Audiencelist', $user_id, $this->Audiencelist->id);
		
		// register the user for the survey
		$this->User->habtmAdd('Survey', $user_id, $survey_id);
	}
	
	/**
	 * Search for surveys by name and unique id
	 * 
	 * @return 
	 */
	function _getSurveys() {
		
		$searchName = "";
		$searchUUID = "";
		$searchType = "";
		$this->set('searchName', '');
		$this->set('searchUUID', '');
		$this->set('searchType', '');
		$display = false;
		$filters = array();
	    
		//Get the search term either from the post data or the session 
	    if(!empty($this->data))
		{
	        $searchName = trim($this->data['Survey']['name']);
			$searchUUID = trim($this->data['Survey']['uuid']);
			$searchType = trim($this->data['SurveyType']['type']);
		}
		elseif($this->Session->check($this->name.'.searchPreResName') || $this->Session->check($this->name.'.searchPreResUUID')
				|| $this->Session->check($this->name.'.searchPreResType'))
		{
			if($this->Session->check($this->name.'.searchPreResName'))
	        	$searchName = $this->Session->read($this->name.'.searchPreResName');
			if($this->Session->check($this->name.'.searchPreResUUID'))
	        	$searchUUID = $this->Session->read($this->name.'.searchPreResUUID');
			if($this->Session->check($this->name.'.searchPreResType'))
	        	$searchType = $this->Session->read($this->name.'.searchPreResType');
		}
	
	    if(!empty($searchName)) {
	    	//Set up the search filters
	        $filters = array('lower(Survey.name) LIKE' => '%'.low($searchName).'%', 'Survey.isDeleted' => '0');
	        $this->Session->write($this->name.'.searchPreResName', $searchName);
			$this->set('searchName', $searchName);
	    }
		
		if(!empty($searchUUID)) {
	    	//Set up the search filters
			$key = 'SUBSTRING(Survey.uuid,2,8) LIKE';
			$value = '%'.$searchUUID.'%';
			$uuidFilters = array($key=>$value);
			$filters = array_merge($filters, $uuidFilters);
			
	        $this->Session->write($this->name.'.searchPreResUUID', $searchUUID);
			$this->set('searchUUID', $searchUUID);
	    }
		
		if(!empty($searchType)) {
	    	//Set up the search filters
			$key = 'SurveyType.type';
			$value = $searchType;
			$typeFilters = array($key=>$value);
			$filters = array_merge($filters, $typeFilters);
			
	        $this->Session->write($this->name.'.searchPreResType', $searchType);
			$this->set('searchType', $searchType);
	    }
		
		$surveys = array();
		// Get the current user
		$active_user = $this->Auth->user();
		$userId = $active_user['User']['id'];
		
		if(!empty($filters)) {
			//Filter by user
			$key = 'Survey.created_by';
			$value = $userId;
			$userFilters = array($key=>$value);
			$filters = array_merge($filters, $userFilters);
		} else {
			$filters = array('Survey.created_by' => $userId);
		}
		
		$surveys = $this->paginate('Survey', $filters);
	    $this->set('surveys', $surveys);
		
		//If the surveys variable is not empty, display results
		if(!empty($surveys)) {
			$display = true;
		}
		$this->set('display', $display);
	}
}
?>
